﻿// Shader-Based-Image-Processing (SBIP)
// http://code.google.com/p/sbip/
//
// Copyright © Frank Nagl, 2009-2012
// admin@franknagl.de
//
namespace SBIP.Filter.NonSBIP
{
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Imaging;
    using Helper;
    using cp = SBIP.Helper.ColorPalette;

    /// <summary>
    /// Pseudo-color segmentation. Pixel with same color value will be grouped 
    /// to one segment.
    /// </summary>
    /// 
    /// <remarks><para>All pixels with same color value will be grouped 
    /// to one segment. It is useful to take  
    /// a <see cref="NSPosterization"/> image as source.</para>
    /// <para>Sample usage:</para>
    /// <code>
    /// Bitmap image = new Bitmap("Cathedral.jpg");  
    /// // create Posterization filter  
    /// BaseNonSBIPFilter filter = new NSPosterization();
    /// image = filter.Apply(image); 
    /// // create NSSimpleColorSegmentation filter  
    /// filter = new NSSimpleColorSegmentation();
    /// image = filter.Apply(image);
    /// </code>
    /// 
    /// <para><b>Initial image:</b></para>
    /// <img src="../../Posterization.png" width="500" height="338" />
    /// <para><b>Result image:</b></para>
    /// <img src="../../SimpleColorSegmentation.jpg" width="500" height="338" />
    /// </remarks>
    /// <seealso cref="Posterization"/>
    /// <seealso cref="NSPosterization"/>
    public class NSSimpleColorSegmentation : BaseNonSBIPFilter
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="NSSimpleColorSegmentation"/> class.
        /// </summary>
        public NSSimpleColorSegmentation()
        {
            SupportedSrcPixelFormats = PixelFormatFlags.Color;
        }

        /// <summary>
        /// Processes the simple color segmentation.
        /// </summary>
        /// <param name="srcData">The source bitmap data.</param>
        /// <param name="dstData">The destination bitmap data.</param>
        protected override void Process(BitmapData srcData, BitmapData dstData)
        {
            int w = srcData.Width;
            int h = srcData.Height;
            int pixelSize = Image.GetPixelFormatSize(srcData.PixelFormat) / 8;
            //All Colors with their id for the colorTable
            Dictionary<Color, int> colors = new Dictionary<Color, int>();
            int offset = srcData.Stride - w * pixelSize;
            int colorId = 0;         

            // do the job
            unsafe
            {
                byte* src = (byte*)srcData.Scan0.ToPointer();
                byte* dst = (byte*)dstData.Scan0.ToPointer();

                // for each line
                for (int y = 0; y < h; y++)
                {
                    // for each pixel in line
                    for (int x = 0; x < w; x++, src += pixelSize, dst += pixelSize)
                    {
                        Color col = Color.FromArgb(
                            src[RGBA.R], src[RGBA.G], src[RGBA.B]);
                        int tempId;

                        if (colors.ContainsKey(col))
                        {
                            colors.TryGetValue(col, out tempId);
                        }
                        else
                        {
                            colorId++;
                            if (colorId == cp.ColorCount)
                                colorId = 0;
                            tempId = colorId;
                            colors.Add(col, tempId);
                        }

                        dst[RGBA.R] = cp.Colors[tempId].R;
                        dst[RGBA.G] = cp.Colors[tempId].G;
                        dst[RGBA.B] = cp.Colors[tempId].B;
                        if (pixelSize == 4)
                        {
                            dst[RGBA.A] = src[RGBA.A];
                        }
                    }
                    src += offset;
                    dst += offset;
                }
            }
        }
    }
}
